﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using ezCloud.Data;
using System.Web.Configuration;
using System.Threading.Tasks;
using System.Configuration;

namespace ezCloud.Api.Common
{
    
    public class PaymentReturnParams
    {
        public paymentResult status { get; set; }
        public string amount { get; set; }
        public string localed { get; set; }
        public string command { get; set; }
        public string version { get; set; }
        public string cardBin { get; set; }
        public string orderInfo { get; set; }
        public string merchantID { get; set; }
        public string authorizeID { get; set; }
        public string merchTxnRef { get; set; }
        public string transactionNo { get; set; }
        public string txnResponseCode { get; set; }
        public string acqResponseCode { get; set; }
        public string message { get; set; }
        public string isDomestic { get; set; }
    }
    public class PaymentParams
    {
        public int vpc_Version { get; set; }
        public string vpc_Currency { get; set; }
        public string vpc_Command { get; set; }
        public string vpc_AccessCode { get; set; }
        public string vpc_Merchant { get; set; }
        public string vpc_Locale { get; set; }
        public string vpc_ReturnURL { get; set; }

        public string vpc_MerchTxnRef { get; set; }

        public string vpc_OrderInfo { get; set; }
        public string vpc_Amount { get; set; }
        public string vpc_TicketNo { get; set; }
        public string AgainLink { get; set; }
        public string Title { get; set; }
        public string vpc_SecureHash { get; set; }

    }
   
    public class OnePayPayment
    {
        private string domesticAPI = ConfigurationSettings.AppSettings["domesticAPI"];// "B561A739EFE3C36A19A8B0FE772B6852";
        private string internationalAPI = ConfigurationSettings.AppSettings["internationalAPI"];//"BC340672BBE1A1C6B7DE553CF20DF556";
        //private string domesticAPI = "A3EFDFABA8653DF2342E8DAC29B51AF0";
        //private string internationalAPI ="6D0870CDE5F24F34F3915FB0045120DB";

        public string createPayment(decimal Amount, decimal additionalAmount, string Description, bool isDomestic, string vpc_Locale, string referralCode)
        {
            
            string amount = Math.Truncate(Amount*100).ToString();
            string hotelReferralCode = null;
            var stringError = "ERROR_";
            PaymentParams pp = new PaymentParams();
            pp.Title = "ezCloud Payment Gateway";
            if (vpc_Locale.Length == 0 || vpc_Locale=="vn") pp.vpc_Locale = "vn";
            else pp.vpc_Locale = "en";
            pp.vpc_Version = 2;
            pp.vpc_Amount = amount;
            string sercure_hash = domesticAPI;

            ezCloudDataContext context = new ezCloudDataContext();
            UserProfile user = UserUtitily.getUserProfile();
            EzPaymentLogs logs = new EzPaymentLogs();

            // Referral Program

            var referralProgram = context.EzReferralPrograms.FirstOrDefault();
            var currentHotel = context.Hotels.Where(ht => ht.HotelId == user.HotelId).FirstOrDefault();
            if (referralProgram != null && currentHotel != null)
            {
                if (referralProgram.Status == true)
                {
                    //if (ReferralProgramUltility.CheckIfHotelFirstPayment(currentHotel.HotelId))
                    //{
                        // Generate Referral Code for hotel B
                        //hotelReferralCode = ReferralProgramUltility.ReferralCodeGenerator(currentHotel.HotelId);
                        //if (hotelReferralCode != null)
                        //{
                        //    var ezReferralCodeB = new EzReferralCodes();
                        //    ezReferralCodeB.HotelId = currentHotel.HotelId;
                        //    ezReferralCodeB.EzReferralProgramId = referralProgram.EzReferralProgramId;
                        //    ezReferralCodeB.Code = hotelReferralCode;
                        //    ezReferralCodeB.CreatedDate = DateTime.UtcNow;
                        //    context.EzReferralCodes.InsertOnSubmit(ezReferralCodeB);
                        //}
                        //else
                        //{
                        //    stringError += "ERROR_OCCURRED_DURING_INITIALIZATION_OF_HOTEL_REFERRAL_CODE";
                        //    return stringError;
                        //}
                        if (referralCode != null && referralCode!="")
                        {
                            var ezReferralCodeA = referralProgram.EzReferralCodesList.FirstOrDefault(rc => rc.Code == referralCode);
                            if (ezReferralCodeA != null && ezReferralCodeA.Hotels != null)
                            {
                                if (ReferralProgramUltility.CheckIfHotelReceivedCodeIsValid((int)ezReferralCodeA.HotelId))
                                {
                                    if (ezReferralCodeA.Hotels.EzAccountsList.FirstOrDefault() != null)
                                    {
                                        logs.HotelIdA = ezReferralCodeA.Hotels.EzAccountsList.FirstOrDefault().HotelId;
                                        logs.CodeA = ezReferralCodeA.Code;
                                    }
                                }
                                else
                                {
                                    stringError += "ERROR_OCCURRED_DUE_TO_HOTEL_WAS_RECEIVED_REFERRAL_CODE_NOT_VALID";
                                    return stringError;
                                }
                            }
                            else
                            {
                                stringError += "ERROR_OCCURRED_DUE_TO_REFERRAL_CODE_OF_HOTEL_MAY_NOT_EXIST";
                                return stringError;
                            }
                        }
                    //}
                    //else
                    //{
                    //    stringError += "ERROR_OCCURRED_DUE_TO_INVALID_HOTEL_FIRST_PAYMENT_CHECKING";
                    //    return stringError;
                    //}

                }
                
            }
            logs.Amount = Amount;
            logs.AmountFee = additionalAmount;
            logs.HotelId = user.HotelId;
            logs.CreatedUserId = user.UserId;
            logs.Status = (int)paymentResult.NotProcessed;
            logs.CreatedDate = DateTime.UtcNow;
            logs.Description = Description;
            logs.PaymentType = 1;
            logs.LogKey = "NEW_PAYMENT";
            context.EzPaymentLogs.InsertOnSubmit(logs);
            context.SubmitChanges();
          

            pp.vpc_MerchTxnRef = ConfigurationSettings.AppSettings["OnepayMerchTxnRef"] + logs.EzPaymentLogsId.ToString();
            //pp.vpc_MerchTxnRef = "ezcloud_" + logs.EzPaymentLogsId.ToString();
            pp.vpc_Command = "pay";
            pp.vpc_ReturnURL = WebConfigurationManager.AppSettings["RootUrl"] + "/paymentCompleted.html" ;
            pp.vpc_OrderInfo = "ezCloud Hotel Payment " + logs.EzPaymentLogsId;
            pp.vpc_TicketNo = HttpContext.Current.Request.UserHostAddress;

            if (isDomestic)
            {
                pp.vpc_Currency = "VND";
                pp.vpc_Merchant = ConfigurationSettings.AppSettings["domestic_vpc_Merchant"];// "EZCLOUD";
                pp.vpc_AccessCode = ConfigurationSettings.AppSettings["domestic_vpc_AccessCode"];// "X807GJ07";
                //pp.vpc_Merchant = "ONEPAY";
                //pp.vpc_AccessCode =  "D67342C2";               
                return createPaymentUrlDomestic(pp, sercure_hash);

            } else
            {
                pp.vpc_Merchant = ConfigurationSettings.AppSettings["international_vpc_Merchant"];// "EZCLOUD";
                pp.vpc_AccessCode = ConfigurationSettings.AppSettings["international_vpc_AccessCode"];// "9E64C1C1";

               // pp.vpc_Merchant = "TESTONEPAY";
               // pp.vpc_AccessCode = "6BEB2546";

                sercure_hash = internationalAPI;
                return createPaymentUrlInternational(pp, sercure_hash);
            }
        }
        
        public string createPaymentUrlInternational(PaymentParams pp, string SECURE_SECRET)
        {
            // Khoi tao lop thu vien va gan gia tri cac tham so gui sang cong thanh toan
            //VPCRequest conn = new VPCRequest("https://mtf.onepay.vn/vpcpay/vpcpay.op");
            VPCRequest conn = new VPCRequest(ConfigurationSettings.AppSettings["international_VPCRequest"]);

            conn.SetSecureSecret(SECURE_SECRET);
            // Add the Digital Order Fields for the functionality you wish to use
            // Core Transaction Fields
            conn.AddDigitalOrderField("AgainLink", "http://pms.ezcloudhotel.vn");
            conn.AddDigitalOrderField("Title", pp.Title);
            conn.AddDigitalOrderField("vpc_Locale", pp.vpc_Locale);//Chon ngon ngu hien thi tren cong thanh toan (vn/en)
            conn.AddDigitalOrderField("vpc_Version", pp.vpc_Version.ToString());
            conn.AddDigitalOrderField("vpc_Command", pp.vpc_Command);
            conn.AddDigitalOrderField("vpc_Merchant", pp.vpc_Merchant);
            conn.AddDigitalOrderField("vpc_AccessCode", pp.vpc_AccessCode);
            conn.AddDigitalOrderField("vpc_MerchTxnRef", pp.vpc_MerchTxnRef);
            conn.AddDigitalOrderField("vpc_OrderInfo", pp.vpc_OrderInfo);
            conn.AddDigitalOrderField("vpc_Amount", pp.vpc_Amount);
            conn.AddDigitalOrderField("vpc_ReturnURL", pp.vpc_ReturnURL);
            // Thong tin them ve khach hang. De trong neu khong co thong tin
            conn.AddDigitalOrderField("vpc_SHIP_Street01", "266 Doi Can");
            conn.AddDigitalOrderField("vpc_SHIP_Provice", "Hanoi");
            conn.AddDigitalOrderField("vpc_SHIP_City", "Hanoi");
            conn.AddDigitalOrderField("vpc_SHIP_Country", "Vietnam");
            conn.AddDigitalOrderField("vpc_Customer_Phone", "");
            conn.AddDigitalOrderField("vpc_Customer_Email", "hotro@ezcloud.vn");
            conn.AddDigitalOrderField("vpc_Customer_Id", "onepay_ezcloud");
            // Dia chi IP cua khach hang
            conn.AddDigitalOrderField("vpc_TicketNo", pp.vpc_TicketNo);
            // Chuyen huong trinh duyet sang cong thanh toan
            String url = conn.Create3PartyQueryString();
            return url;
        }
        public async Task SendPaymentStatusNotificationEmail(int hotelId, string hotelName, string email, string Fullname, PaymentReturnParams paymentReturn, Decimal amount, int ezPaymentLogId)
        {
            //string Amount = String.Format("{{0:0.00}}", amount);
            ezCloudDataContext context = new ezCloudDataContext();
            string Amount = amount.ToString("c", Utilities.GetCurrencyFormatProviderSymbolDecimals("VND"));
            string Status = "";
            string StatusEN = "";
            switch (paymentReturn.status)
            {
                case paymentResult.OK:
                    Status = " Đã thanh toán thành công.";
                    StatusEN=" Payment successful.";
                    break;
                case paymentResult.Pending:
                    Status = " Đang chờ xử lý từ ngân hàng.";
                    StatusEN = " Payment pending.";
                    break;
                case paymentResult.Failed:
                    string errorCode = "";
                    if (paymentReturn.isDomestic=="true")
                    {
                        errorCode = "DOMESTIC_ERROR_" + paymentReturn.txnResponseCode;
                    }
                    else
                    {
                        errorCode = "INTERNATIONAL_ERROR_" + paymentReturn.txnResponseCode;
                    }
                    var language = context.LanguageItemValues.Where(l => l.LanguageItems.LanguageCode == errorCode).ToList();
                    var languageVn = errorCode ;
                    var languageEn = errorCode ;
                    if (language != null)
                    {
                        if (language.Where(t => t.Languages.LanguageCode == "vn").FirstOrDefault()!=null)
                            languageVn = language.Where(t => t.Languages.LanguageCode == "vn").FirstOrDefault().LanguageItemValue;
                        if (language.Where(t => t.Languages.LanguageCode == "en").FirstOrDefault()!=null)
                            languageEn = language.Where(t => t.Languages.LanguageCode == "en").FirstOrDefault().LanguageItemValue;
                    }
                    Status = " Không thành công (" + languageVn + ")";
                    StatusEN = " Payment failed (" + languageEn + ")";
                    break;
                
                default:
                    Status = " Chưa được xử lý.";
                    StatusEN = " Payment not process.";
                    break;
            }
            string subject = "ezCloud Hotel -  Payment information for hotel / Thông tin thanh toán cho khách sạn: " + hotelName+ "(Hotel Id:"+hotelId.ToString()+")";
            EmailSender.SendPaymentStatus(email, subject, Fullname, Amount, Status,StatusEN, ezPaymentLogId);
            return;
        }
        public string createPaymentUrlDomestic(PaymentParams pp, string SECURE_SECRET)
        {

            // Khoi tao lop thu vien va gan gia tri cac tham so gui sang cong thanh toan
            //VPCRequest conn = new VPCRequest("https://mtf.onepay.vn/onecomm-pay/vpc.op");
            VPCRequest conn = new VPCRequest(ConfigurationSettings.AppSettings["domestic_VPCRequest"]);
            
            conn.SetSecureSecret(SECURE_SECRET);
            // Add the Digital Order Fields for the functionality you wish to use
            // Core Transaction Fields
            conn.AddDigitalOrderField("Title", pp.Title);
            conn.AddDigitalOrderField("vpc_Locale", pp.vpc_Locale);//Chon ngon ngu hien thi tren cong thanh toan (vn/en)
            conn.AddDigitalOrderField("vpc_Version", pp.vpc_Version.ToString());
            conn.AddDigitalOrderField("vpc_Command", pp.vpc_Command);
            conn.AddDigitalOrderField("vpc_Merchant", pp.vpc_Merchant);
            conn.AddDigitalOrderField("vpc_AccessCode", pp.vpc_AccessCode);
            conn.AddDigitalOrderField("vpc_MerchTxnRef", pp.vpc_MerchTxnRef);
            conn.AddDigitalOrderField("vpc_OrderInfo", pp.vpc_OrderInfo);
            conn.AddDigitalOrderField("vpc_Amount", pp.vpc_Amount);
            conn.AddDigitalOrderField("vpc_Currency", pp.vpc_Currency);
            conn.AddDigitalOrderField("vpc_ReturnURL", pp.vpc_ReturnURL);            
            // Thong tin them ve khach hang. De trong neu khong co thong tin
            conn.AddDigitalOrderField("vpc_SHIP_Street01", "266 Doi Can");
            conn.AddDigitalOrderField("vpc_SHIP_Provice", "Hanoi");
            conn.AddDigitalOrderField("vpc_SHIP_City", "Hanoi");
            conn.AddDigitalOrderField("vpc_SHIP_Country", "Vietnam");
            conn.AddDigitalOrderField("vpc_Customer_Phone", "");
            conn.AddDigitalOrderField("vpc_Customer_Email", "hotro@ezcloud.vn");
            conn.AddDigitalOrderField("vpc_Customer_Id", "onepay_ezcloud");
            // Dia chi IP cua khach hang
            conn.AddDigitalOrderField("vpc_TicketNo", pp.vpc_TicketNo);
            // Chuyen huong trinh duyet sang cong thanh toan
            String url = conn.Create3PartyQueryString();
            return url;
        }
        public PaymentReturnParams ProcessReturnUrl(bool isIPN)
        {
            PaymentReturnParams paymentReturn = new PaymentReturnParams();
            string SECURE_SECRET_Domestic = domesticAPI;
            string SECURE_SECRET_International = internationalAPI;
            string hashvalidateResult = "";
            // Khoi tao lop thu vien
            VPCRequest conn = new VPCRequest("http://onepay.vn");
            conn.SetSecureSecret(SECURE_SECRET_Domestic);
            // Xu ly tham so tra ve va kiem tra chuoi du lieu ma hoa
            hashvalidateResult = conn.Process3PartyResponse(isIPN ? HttpContext.Current.Request.Form : HttpContext.Current.Request.QueryString);

            // Lay gia tri tham so tra ve tu cong thanh toan
            String vpc_TxnResponseCode = conn.GetResultField("vpc_TxnResponseCode", "Unknown");
            paymentReturn.amount = conn.GetResultField("vpc_Amount", "Unknown");
            paymentReturn.localed = conn.GetResultField("vpc_Locale", "Unknown");
            paymentReturn.command = conn.GetResultField("vpc_Command", "Unknown");
            paymentReturn.version = conn.GetResultField("vpc_Version", "Unknown");
            paymentReturn.cardBin = conn.GetResultField("vpc_Card", "Unknown");
            paymentReturn.orderInfo = conn.GetResultField("vpc_OrderInfo", "Unknown");
            paymentReturn.merchantID = conn.GetResultField("vpc_Merchant", "Unknown");
            paymentReturn.authorizeID = conn.GetResultField("vpc_AuthorizeId", "Unknown");
            paymentReturn.merchTxnRef = conn.GetResultField("vpc_MerchTxnRef", "Unknown");
            paymentReturn.transactionNo = conn.GetResultField("vpc_TransactionNo", "Unknown");
            paymentReturn.acqResponseCode = conn.GetResultField("vpc_AcqResponseCode", "Unknown");
            paymentReturn.isDomestic = conn.GetResultField("isDomestic", "Unknown");
            paymentReturn.txnResponseCode = vpc_TxnResponseCode;
            paymentReturn.message = conn.GetResultField("vpc_Message", "Unknown");
            if (hashvalidateResult == "CORRECTED" && paymentReturn.txnResponseCode.Trim() == "0")
            {
                paymentReturn.status = paymentResult.OK;
            }
            else if (hashvalidateResult == "INVALIDATED" && paymentReturn.txnResponseCode.Trim() == "0")
            {
                //check if from International process
                conn.SetSecureSecret(SECURE_SECRET_International);
                
                hashvalidateResult = conn.Process3PartyResponse(isIPN ? HttpContext.Current.Request.Form : HttpContext.Current.Request.QueryString);
                if (hashvalidateResult == "CORRECTED" && paymentReturn.txnResponseCode.Trim() == "0")
                {
                    paymentReturn.status = paymentResult.OK;
                } else if (hashvalidateResult == "INVALIDATED" && paymentReturn.txnResponseCode.Trim() == "0")
                {
                    paymentReturn.status = paymentResult.Pending;
                } else
                    paymentReturn.status = paymentResult.Failed;
            } else
            paymentReturn.status = paymentResult.Failed;
            try {
                paymentReturn.merchTxnRef = paymentReturn.merchTxnRef.Substring(ConfigurationSettings.AppSettings["OnepayMerchTxnRef"].Length);
                int logId = Int32.Parse(paymentReturn.merchTxnRef);
                ezCloudDataContext context = new ezCloudDataContext();
                var log = context.EzPaymentLogs.ByEzPaymentLogsId(logId).FirstOrDefault();
                var hotelAccountA = context.EzAccounts.FirstOrDefault(a => a.HotelId == log.HotelIdA);
                if (log != null)
                {
                    if (log.Status != (int) paymentReturn.status)
                    {
                        var user = UserUtitily.getUserProfileById(log.CreatedUserId);
                        var hotel = context.Hotels.Where(h => h.HotelId == user.HotelId).FirstOrDefault();
                        var logReferralProgramB = new EzPaymentLogs();
                        var ezRPLog = new EzReferralProgramLogs();
                        if (paymentReturn.status == paymentResult.OK)
                        {
                            var hotelAccountB = context.EzAccounts.FirstOrDefault(a => a.HotelId == log.HotelId);
                            if (hotelAccountB != null)
                            {
                                hotelAccountB.Amount += log.Amount;
                                hotelAccountB.AmountFee += log.AmountFee;

                                // ReferralProgram must be ACTIVED
                                var referralProgram = context.EzReferralPrograms.FirstOrDefault(rp => rp.Status == true);
                                if (referralProgram != null)
                                {
                                    if (log.HotelIdA != null && log.CodeA != null)
                                    {
                                        
                                        // 2 conditions must be checked AGAIN
                                        if (hotelAccountA != null && ReferralProgramUltility.CheckIfHotelReceivedCodeIsValid((int)log.HotelIdA) && ReferralProgramUltility.CheckIfHotelFirstPayment(hotel.HotelId))
                                        {
                                            
                                            logReferralProgramB.Amount = 0;
                                            logReferralProgramB.AmountFee = log.Amount * referralProgram.CommisionRateB / 100;
                                            logReferralProgramB.HotelId = user.HotelId;
                                            logReferralProgramB.CreatedUserId = user.UserId;
                                            logReferralProgramB.Status = 0;//log.Status;
                                            logReferralProgramB.CreatedDate = DateTime.UtcNow;
                                            logReferralProgramB.Description = "Amount fee from hotel " + hotelAccountA.Hotels.HotelName;
                                            logReferralProgramB.PaymentType = 1;
                                            logReferralProgramB.LogKey = "REFERRAL_PROGRAM";
                                            logReferralProgramB.HotelIdA = log.HotelIdA;
                                            logReferralProgramB.CodeA = log.CodeA;
                                            context.EzPaymentLogs.InsertOnSubmit(logReferralProgramB);

                                            
                                            ezRPLog.EzReferralProgramId = referralProgram.EzReferralProgramId;
                                            ezRPLog.HotelIdA = log.HotelIdA;
                                            ezRPLog.HotelIdB = log.HotelId;
                                            ezRPLog.TotalAmountFeeA = hotelAccountA.AmountFee;
                                            ezRPLog.CommisionAmountA = log.Amount * referralProgram.CommisionRateA / 100;
                                            ezRPLog.CommisionAmountB = log.Amount * referralProgram.CommisionRateB / 100;
                                            ezRPLog.CodeA = log.CodeA;
                                            ezRPLog.CreatedDate = DateTime.UtcNow;
                                            context.EzReferralProgramLogs.InsertOnSubmit(ezRPLog);

                                            hotelAccountA.AmountFee += log.Amount * referralProgram.CommisionRateA / 100;
                                            hotelAccountB.AmountFee += log.Amount * referralProgram.CommisionRateB / 100;


                                            if (paymentReturn.status == paymentResult.OK)
                                            {

                                                // SAU KHI SUBMIT THANH CONG MOI GUI MAIL
                                                if (logReferralProgramB != null && ezRPLog != null && hotelAccountA != null)
                                                {
                                                    // GUI MAIL CHO KHACH SAN B: hotel.HotelName - Amount Fee: logRelogReferralProgramB.AmountFee
                                                    decimal _amount = (decimal)log.Amount;
                                                    string TotalAmount = _amount.ToString("c", Utilities.GetCurrencyFormatProviderSymbolDecimals("VND"));
                                                    decimal _commistionAmountB = (decimal)ezRPLog.CommisionAmountB;
                                                    string CommisionAmount_B = _commistionAmountB.ToString("c", Utilities.GetCurrencyFormatProviderSymbolDecimals("VND"));
                                                    var hotelOwner = context.Hotels.Where(m => m.HotelId == hotelAccountB.HotelId).Single();
                                                    var userOwner = context.AspNetUsers.Where(o => o.Id == hotelOwner.HotelOwnerId).FirstOrDefault();
                                                    EmailSender.SendEmailReferralCommision_B(userOwner.Email, userOwner.UserName, log.CodeA, hotelAccountA.Hotels.HotelName, hotelAccountB.Hotels.HotelName,(int)hotelAccountB.HotelId,  CommisionAmount_B, TotalAmount);

                                                    // GUI MAIL CHO KHACH SAN A: hotelAccountA.Hotels.HotelName - Amount Fee: ezRPLog.CommisionAmountA
                                                    decimal _commistionAmountA = (decimal)ezRPLog.CommisionAmountA;
                                                    string CommisionAmount_A = _commistionAmountA.ToString("c", Utilities.GetCurrencyFormatProviderSymbolDecimals("VND"));
                                                    hotelOwner = context.Hotels.Where(m => m.HotelId == hotelAccountA.HotelId).Single();
                                                    userOwner = context.AspNetUsers.Where(o => o.Id == hotelOwner.HotelOwnerId).FirstOrDefault();
                                                    EmailSender.SendEmailReferralCommision_A(userOwner.Email, userOwner.UserName, log.CodeA, hotelAccountA.Hotels.HotelName,(int)hotelAccountA.HotelId, hotelAccountB.Hotels.HotelName, CommisionAmount_A, TotalAmount);
                                                }

                                            }
                                        }
                                        else
                                        {
                                            // GUI MAIL CHO ANH DUNG LOI XAY RA NGAM
                                            // LOI CheckIfHotelReceivedCodeIsValid
                                            // LOI CheckIfHotelFirstPayment
                                        }
                                    }
                                }
                            }
                        }
                        log.Status = (int)paymentReturn.status;
                        log.OnePayPaymentLog = log.Status.ToString() + " - [" + (isIPN ? HttpContext.Current.Request.Form : HttpContext.Current.Request.QueryString) + "]";

                        context.SubmitChanges();

                        if (paymentReturn.status == paymentResult.OK)
                        {
                            BackendPaymentUtility.CalculateRemainingDays((int)log.HotelId, context);

                            // GUI MAIL TAO CODE CHO KHACH SAN currentHotel.HotelName
                            if (ReferralProgramUltility.CreateHotelReferralCode((int)log.HotelId) == true)
                            {
                                string hotelReferralCode = ReferralProgramUltility.ReferralCodeGenerator((int)log.HotelId);
                                if (hotelReferralCode != null)
                                {
                                   
                                    var hotelOwner = context.Hotels.Where(m => m.HotelId == (int)log.HotelId).Single();
                                    var userOwner = context.AspNetUsers.Where(o => o.Id == hotelOwner.HotelOwnerId).FirstOrDefault();
                                    EmailSender.SendEmailReferralCode(userOwner.Email, userOwner.UserName, hotelReferralCode, log.Hotels.HotelName, log.Hotels.HotelId);
                                }

                            }
                        }
                        var hotelName = "";
                        if (hotel != null) hotelName = hotel.HotelName;
                        //string IPNN
                        //SendPaymentStatusNotificationEmail(hotel.HotelId, hotelName, user.Email, user.FullName, paymentReturn, (decimal)log.Amount, log.EzPaymentLogsId);
                        
                    }
                }
            } catch (Exception ex)
            {

            }
            return paymentReturn;
            
        }
    }

    public class VPCRequest
    {
        Uri _address;
        SortedList<String, String> _requestFields = new SortedList<String, String>(new VPCStringComparer());
        String _rawResponse;
        SortedList<String, String> _responseFields = new SortedList<String, String>(new VPCStringComparer());
        String _secureSecret;


        public VPCRequest(String URL)
        {
            _address = new Uri(URL);
        }

        public void SetSecureSecret(String secret)
        {
            _secureSecret = secret;
        }

        public void AddDigitalOrderField(String key, String value)
        {
            if (!String.IsNullOrEmpty(value))
            {
                _requestFields.Add(key, value);
            }
        }

        public String GetResultField(String key, String defValue)
        {
            String value;
            if (_responseFields.TryGetValue(key, out value))
            {
                return value;
            }
            else
            {
                return defValue;
            }
        }

        public String GetResultField(String key)
        {
            return GetResultField(key, "");
        }

        private String GetRequestRaw()
        {
            StringBuilder data = new StringBuilder();
            foreach (KeyValuePair<string, string> kvp in _requestFields)
            {
                if (!String.IsNullOrEmpty(kvp.Value))
                {
                    data.Append(kvp.Key + "=" + HttpUtility.UrlEncode(kvp.Value) + "&");
                }
            }
            //remove trailing & from string
            if (data.Length > 0)
                data.Remove(data.Length - 1, 1);
            return data.ToString();
        }

        public string GetTxnResponseCode()
        {
            return GetResultField("vpc_TxnResponseCode");
        }

        //_____________________________________________________________________________________________________
        // Three-Party order transaction processing

        public String Create3PartyQueryString()
        {
            StringBuilder url = new StringBuilder();
            //Payment Server URL
            url.Append(_address);
            url.Append("?");
            //Create URL Encoded request string from request fields 
            url.Append(GetRequestRaw());
            //Hash the request fields
            url.Append("&vpc_SecureHash=");
            url.Append(CreateSHA256Signature(true));
            return url.ToString();
        }

        public string Process3PartyResponse(System.Collections.Specialized.NameValueCollection nameValueCollection)
        {
            _responseFields.Clear();
            foreach (string item in nameValueCollection)
            {
                if (!item.Equals("vpc_SecureHash") && !item.Equals("vpc_SecureHashType"))
                {
                    _responseFields.Add(item, nameValueCollection[item]);
                }

            }

            if (!nameValueCollection["vpc_TxnResponseCode"].Equals("0") && !String.IsNullOrEmpty(nameValueCollection["vpc_Message"]))
            {
                if (!String.IsNullOrEmpty(nameValueCollection["vpc_SecureHash"]))
                {
                    if (!CreateSHA256Signature(false).Equals(nameValueCollection["vpc_SecureHash"]))
                    {
                        return "INVALIDATED";
                    }
                    return "CORRECTED";
                }
                return "CORRECTED";
            }

            if (String.IsNullOrEmpty(nameValueCollection["vpc_SecureHash"]))
            {
                return "INVALIDATED";//no sercurehash response
            }
            if (!CreateSHA256Signature(false).Equals(nameValueCollection["vpc_SecureHash"]))
            {
                return "INVALIDATED";
            }
            return "CORRECTED";
        }

        //_____________________________________________________________________________________________________

        private class VPCStringComparer : IComparer<String>
        {
            /*
             <summary>Customised Compare Class</summary>
             <remarks>
             <para>
             The Virtual Payment Client need to use an Ordinal comparison to Sort on 
             the field names to create the SHA256 Signature for validation of the message. 
             This class provides a Compare method that is used to allow the sorted list 
             to be ordered using an Ordinal comparison.
             </para>
             </remarks>
             */

            public int Compare(String a, String b)
            {
                /*
                 <summary>Compare method using Ordinal comparison</summary>
                 <param name="a">The first string in the comparison.</param>
                 <param name="b">The second string in the comparison.</param>
                 <returns>An int containing the result of the comparison.</returns>
                 */

                // Return if we are comparing the same object or one of the 
                // objects is null, since we don't need to go any further.
                if (a == b) return 0;
                if (a == null) return -1;
                if (b == null) return 1;

                // Ensure we have string to compare
                string sa = a as string;
                string sb = b as string;

                // Get the CompareInfo object to use for comparing
                System.Globalization.CompareInfo myComparer = System.Globalization.CompareInfo.GetCompareInfo("en-US");
                if (sa != null && sb != null)
                {
                    // Compare using an Ordinal Comparison.
                    return myComparer.Compare(sa, sb, System.Globalization.CompareOptions.Ordinal);
                }
                throw new ArgumentException("a and b should be strings.");
            }
        }

        //______________________________________________________________________________
        // SHA256 Hash Code

        public string CreateSHA256Signature(bool useRequest)
        {
            // Hex Decode the Secure Secret for use in using the HMACSHA256 hasher
            // hex decoding eliminates this source of error as it is independent of the character encoding
            // hex decoding is precise in converting to a byte array and is the preferred form for representing binary values as hex strings. 
            byte[] convertedHash = new byte[_secureSecret.Length / 2];
            for (int i = 0; i < _secureSecret.Length / 2; i++)
            {
                convertedHash[i] = (byte)Int32.Parse(_secureSecret.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
            }

            // Build string from collection in preperation to be hashed
            StringBuilder sb = new StringBuilder();
            SortedList<String, String> list = (useRequest ? _requestFields : _responseFields);
            foreach (KeyValuePair<string, string> kvp in list)
            {
                if (kvp.Key.StartsWith("vpc_") || kvp.Key.StartsWith("user_"))
                    sb.Append(kvp.Key + "=" + kvp.Value + "&");
            }
            // remove trailing & from string
            if (sb.Length > 0)
                sb.Remove(sb.Length - 1, 1);

            // Create secureHash on string
            string hexHash = "";
            using (HMACSHA256 hasher = new HMACSHA256(convertedHash))
            {
                byte[] hashValue = hasher.ComputeHash(Encoding.UTF8.GetBytes(sb.ToString()));
                foreach (byte b in hashValue)
                {
                    hexHash += b.ToString("X2");
                }
            }
            return hexHash;
        }
    }

    public enum paymentResult { OK = 0, Pending = 1,  Failed = 2, NotProcessed = 3};
    
}